package com.zenithmind.user.security;

import java.time.Duration;
import java.util.Map;

/**
 * 令牌服务接口
 * 遵循接口隔离原则：分离令牌的不同操作
 * 遵循依赖倒置原则：定义抽象接口，便于替换不同的令牌实现
 */
public interface TokenService {
    
    /**
     * 生成访问令牌
     * 
     * @param claims 令牌声明
     * @return 访问令牌
     */
    String generateAccessToken(Map<String, Object> claims);
    
    /**
     * 生成刷新令牌
     * 
     * @param claims 令牌声明
     * @return 刷新令牌
     */
    String generateRefreshToken(Map<String, Object> claims);
    
    /**
     * 生成自定义过期时间的令牌
     * 
     * @param claims 令牌声明
     * @param expiration 过期时间
     * @return 令牌
     */
    String generateToken(Map<String, Object> claims, Duration expiration);
    
    /**
     * 验证令牌
     * 
     * @param token 令牌
     * @return 令牌信息
     */
    TokenInfo validateToken(String token);
    
    /**
     * 刷新令牌
     * 
     * @param refreshToken 刷新令牌
     * @return 新的访问令牌
     */
    String refreshAccessToken(String refreshToken);
    
    /**
     * 撤销令牌
     * 
     * @param token 令牌
     */
    void revokeToken(String token);
    
    /**
     * 检查令牌是否被撤销
     * 
     * @param token 令牌
     * @return 是否被撤销
     */
    boolean isTokenRevoked(String token);
    
    /**
     * 令牌信息类
     */
    class TokenInfo {
        private final String subject;
        private final Map<String, Object> claims;
        private final boolean valid;
        private final String errorMessage;
        
        public TokenInfo(String subject, Map<String, Object> claims) {
            this.subject = subject;
            this.claims = claims;
            this.valid = true;
            this.errorMessage = null;
        }
        
        public TokenInfo(String errorMessage) {
            this.subject = null;
            this.claims = null;
            this.valid = false;
            this.errorMessage = errorMessage;
        }
        
        public String getSubject() { return subject; }
        public Map<String, Object> getClaims() { return claims; }
        public boolean isValid() { return valid; }
        public String getErrorMessage() { return errorMessage; }
        
        public <T> T getClaim(String name, Class<T> type) {
            if (claims == null) return null;
            Object value = claims.get(name);
            return type.isInstance(value) ? type.cast(value) : null;
        }
        
        public String getUserId() {
            return getClaim("user_id", String.class);
        }
        
        public String getUsername() {
            return getClaim("preferred_username", String.class);
        }
        
        @SuppressWarnings("unchecked")
        public java.util.List<String> getRoles() {
            return getClaim("roles", java.util.List.class);
        }
    }
}
